
#ifndef __WAVEFRONT_H__
#define __WAVEFRONT_H__
   
#include "mesh.h"

#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
   
using namespace std;
   
class NodeStack {
   
public:
   NodeStack();
   NodeStack(uint id, float p);
   
   uint    nodeid;
   float   penalty;
};

class Node {
   
public:
   Node();
   Node(Vertex_handle vh, Halfedge_handle parent);
   ~Node();

   void print();
   
   Vertex_handle     h;      // the vertex handle
   Halfedge_handle   hprev;  // 
   Halfedge_handle   hnext;  // 
   Halfedge_handle   hparent;
   
   int               nodeant; // id no node anterior na lista de nodes
   int               nodepost; // id no node anterior na lista de nodes
   int               wfront;  // id do wfront na lista de wavefronts
   int               idseed;  // id do seed na lista de sementes
   float             cost;
   float             penalty;
   bool              active_indicator;
};

class compareNodeStack {
public:
   bool operator() (const NodeStack &u, const NodeStack &v) const {
      return u.penalty > v.penalty;
   }
};
   
class WaveFront {
   
public:
    WaveFront();
    WaveFront(int idSeed);
   ~WaveFront();
   
   void print();
   
   int                     nNodes;
   Vector3                 sumVertices;
   Vector3                 sumEdges;
   Vector3                 sumNormals;
   Vector3                 dpEdges;       // principal direction of edges
   Vector3                 dpNormals;     // principal direction of normals
   Vector3                 masscenter;    // center of mass
   
   //~ float                   maxcost;       // maximum cost
   //~ float                   mincost;       // minimum cost
   //~ float                   sumcost;
   //~ float                   avgcost;
   
   //~ Vector3                 transd;        // transversal direction
   float                   ray2;          // squared ray
   bool                    activity;      // activity flag
   int                     idseed;        // id do seed na lista de sementes
   int                     firstNode;     // first vertex
   int                     band;
   int                     oldestnode;
};
   
class OpenList {
   
public:
   OpenList();

   // Builds a openlist (and their wavefront) using a seed
   OpenList(list<Vertex_handle> &ring, int idseed, Mesh *model, WaveFront &wf);
   
   // Builds a openlist (and their wavefront) using a ring of vertices
   OpenList(Vertex_handle h, int idseed, Mesh *model, WaveFront &wf);
   ~OpenList();
   
   float compute_penalty(Mesh *model, float cost, WaveFront &wf, Vertex_handle, 
                        const Vector3 &uhp, const Vector3 &uha, const Vector3 &uhn);
   
   Vector3 unitary(Mesh *model, Halfedge_handle h);
   
   void pushback(Node& n);
   
   void print();
   void print_queue();
   void print(Mesh *model);
   
   vector<Node>                                                     nodes;
   priority_queue<NodeStack, vector<NodeStack>, compareNodeStack>   queue;
};
   
#endif
